/*
	此模块用于调用AI推理服务，主要是进行服务封装
	目前AI服务部署在客户的服务器：60.208.118.42，端口要做映射，从30000-30100
*/

package common

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"mime/multipart"
	"net/http"
	"net/url"
	"oa-rest/config"
	"os"
	"path/filepath"
	"time"
)

// Client 简化版HTTP客户端
type Client struct {
	BaseURL string
	Client  *http.Client
	headers map[string]string
}

var (
	AIHttpClient         *Client
	LocalQueryHttpClient *Client
	DocQAHttpClient      *Client
	DocIndexHttpClient   *Client
)

// NewClient 创建新的HTTP客户端
func NewClient(baseURL string) *Client {
	return &Client{
		BaseURL: baseURL,
		Client: &http.Client{
			Timeout: 30 * time.Second,
		},
		headers: map[string]string{
			"User-Agent": "Simple-HTTP-Client/1.0",
			"Accept":     "application/json",
		},
	}
}

// SetHeader 设置请求头
func (c *Client) SetHeader(key, value string) {
	c.headers[key] = value
}

// SetTimeout 设置超时时间
func (c *Client) SetTimeout(timeout time.Duration) {
	c.Client.Timeout = timeout
}

// Get 发送GET请求
func (c *Client) Get(endpoint string, params map[string]string, result interface{}) error {
	// 构建URL
	urlStr := c.buildURL(endpoint, params)

	req, err := http.NewRequest("GET", urlStr, nil)
	if err != nil {
		return err
	}

	// 设置请求头
	for k, v := range c.headers {
		req.Header.Set(k, v)
	}

	resp, err := c.Client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	return c.parseJSONResponse(resp, result)
}

// PostJSON 发送JSON格式的POST请求
func (c *Client) PostJSON(endpoint string, data interface{}, result interface{}) error {
	// 序列化JSON数据
	jsonData, err := json.Marshal(data)
	if err != nil {
		return err
	}

	urlStr := c.buildURL(endpoint, nil)
	log.Println(urlStr)
	req, err := http.NewRequest("POST", urlStr, bytes.NewBuffer(jsonData))
	if err != nil {
		return err
	}

	// 设置请求头
	for k, v := range c.headers {
		req.Header.Set(k, v)
	}
	req.Header.Set("Content-Type", "application/json")

	resp, err := c.Client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	return c.parseJSONResponse(resp, result)
}

// PostForm 发送表单格式的POST请求（支持文件上传）
func (c *Client) PostForm(endpoint string, formData map[string]string, files map[string]string, result interface{}) error {
	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)

	// 添加文件
	for fieldName, filePath := range files {
		file, err := os.Open(filePath)
		if err != nil {
			return err
		}
		defer file.Close()

		part, err := writer.CreateFormFile(fieldName, filepath.Base(filePath))
		if err != nil {
			return err
		}
		_, err = io.Copy(part, file)
		if err != nil {
			return err
		}
	}

	// 添加普通表单字段
	for key, value := range formData {
		writer.WriteField(key, value)
	}

	writer.Close()

	urlStr := c.buildURL(endpoint, nil)
	req, err := http.NewRequest("POST", urlStr, body)
	if err != nil {
		return err
	}

	// 设置请求头
	for k, v := range c.headers {
		req.Header.Set(k, v)
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())

	resp, err := c.Client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	return c.parseJSONResponse(resp, result)
}

func (c *Client) PostFile(endpoint string, file *multipart.FileHeader) error {
	src, err := file.Open()
	if err != nil {
		return err
	}
	defer src.Close()

	// 准备请求体
	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)

	// 创建文件部分
	part, err := writer.CreateFormFile("file", file.Filename)
	if err != nil {
		return fmt.Errorf("创建表单文件失败: %v", err)
	}

	// 拷贝文件内容
	_, err = io.Copy(part, src)
	if err != nil {
		return fmt.Errorf("拷贝文件内容失败: %v", err)
	}

	// 关闭writer
	err = writer.Close()
	if err != nil {
		return fmt.Errorf("关闭multipart写入器失败: %v", err)
	}

	// 创建请求
	req, err := http.NewRequest("POST", endpoint, body)
	if err != nil {
		return fmt.Errorf("创建请求失败: %v", err)
	}

	// 设置Content-Type
	req.Header.Set("Content-Type", writer.FormDataContentType())

	// 发送请求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("发送请求失败: %v", err)
	}
	defer resp.Body.Close()

	// 读取并打印响应
	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("读取响应失败: %v", err)
	}

	fmt.Printf("响应状态码: %d\n", resp.StatusCode)
	fmt.Printf("响应内容: %s\n", respBody)

	return nil
}

// buildURL 构建完整的URL
func (c *Client) buildURL(endpoint string, params map[string]string) string {
	urlStr := c.BaseURL + endpoint

	if len(params) > 0 {
		query := url.Values{}
		for k, v := range params {
			query.Add(k, v)
		}
		urlStr += "?" + query.Encode()
	}

	return urlStr
}

// parseJSONResponse 解析JSON响应
func (c *Client) parseJSONResponse(resp *http.Response, result interface{}) error {
	// 检查状态码
	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		return fmt.Errorf("HTTP error: %s", resp.Status)
	}

	// 读取响应体
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return err
	}

	// 解析JSON
	if result != nil {
		return json.Unmarshal(body, result)
	}

	return nil
}

func InitAIClient() {
	c := NewClient(config.AIUrl)
	c.SetHeader("Accept", "application/json")
	AIHttpClient = c

	// 初始化本地查询服务客户端
	localQueryUrl := "http://60.208.118.42:30003"
	localClient := NewClient(localQueryUrl)
	localClient.SetHeader("Accept", "application/json")
	LocalQueryHttpClient = localClient

	// 初始化文档问答服务客户端
	docQAUrl := "http://60.208.118.42:30006"
	docQAClient := NewClient(docQAUrl)
	docQAClient.SetHeader("Accept", "application/json")
	DocQAHttpClient = docQAClient

	// 初始化文档索引服务客户端
	docIndexUrl := "http://60.208.118.42:30006"
	docIndexClient := NewClient(docIndexUrl)
	docIndexClient.SetHeader("Accept", "application/json")
	DocIndexHttpClient = docIndexClient
}
